﻿//Author:Michal Sporna
//License: https://operationsneakpeek.codeplex.com/license

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace Util
{
    public static class ErrorLogging
    {
        #region private fields
        //Exception that has recently been logged
        private static Exception _LoggedException;
        private static bool _ScreensSet = false;

        #endregion

        #region log and display error

        /// <summary>
        /// log exception (save recently occured exception)
        /// set flag ShowException to true
        /// </summary>
        /// <param name="ex"></param>
        public static void LogError(Exception ex)
        {
            _LoggedException = ex;


            if (!_ScreensSet)
            {
                //set previous screen
                Util.Cache.PreviousScreen = Util.Cache.CurrentScreen;
                //set current screen
                Util.Cache.CurrentScreen = Cache.Screen.Error;

                _ScreensSet = true;
            }

        }


        /// <summary>
        /// draw a rectangle with error info in it
        /// </summary>
        /// <param name="ex"></param>
        public static void ShowError()
        {
            try
            {
                if (_LoggedException == null)
                {
                    return;
                }


                //declare
                Texture2D errorPopup;
                Texture2D closeButton;
                Classes.Font font;
                Classes.Font smallFont;
                List<string> exceptionTitleLines = new List<string>();
                List<string> exceptionStackTraceLines = new List<string>();
                int titleLineStep = 15; //if exception message has more than 1 line, then divide it into lines and loop through all, each time add some value to X (to draw line lower)
                int stackTraceStep = 145;
                string helpString = string.Empty;


                //process
                if (Cache.spriteBatch != null)
                {
                    //get errorPopup texture
                    errorPopup = Util.Cache.GetTexture("errorPopup").Text2D;
                    //get fint
                    font = Util.Cache.GetFont("default");
                    //get close button
                    closeButton = Util.Cache.GetTexture("button1").Text2D;
                    //get small font
                    smallFont = Util.Cache.GetFont("small");


                    //draw
                    
                    //draw popup
                    Cache.Draw(errorPopup, new Microsoft.Xna.Framework.Rectangle(0, 0, Cache.GraphicsDevice.Viewport.Width, Cache.GraphicsDevice.Viewport.Height), Color.White);
                    //draw strings
                    #region error title
                    //title
                    //if title's lenght is more than lenght of error popup, then divide it into lines
                    if (font.FontFace.MeasureString(_LoggedException.Message).Length() > Cache.GraphicsDevice.Viewport.Width - 40)
                    {
                        //declare
                        int charProcessed = 1;
                        string exceptionMessage = _LoggedException.Message;


                        //Loop and keep dividing until exception message still has some chars
                        while (exceptionMessage.Length > 0)
                        {
                            //keep dividing until each line is less than vieport's width
                            while (font.FontFace.MeasureString(helpString).Length() < Cache.GraphicsDevice.Viewport.Width - 40)
                            {


                                //keep pulling chars out of error message while it's less than vieport's width
                                helpString = exceptionMessage.Substring(0, charProcessed);
                                charProcessed += 1;

                                if (charProcessed > exceptionMessage.Length)
                                {
                                    break;
                                }
                            }

                            //add to the list of lines
                            if (helpString != string.Empty)
                            {
                                exceptionTitleLines.Add(helpString);
                            }

                            //remove  a help string from message
                            exceptionMessage = exceptionMessage.Remove(0, charProcessed - 1);
                            //reset char processed
                            charProcessed = 1;
                            helpString = string.Empty;
                        }

                    }
                    else
                    {
                        exceptionTitleLines.Add(_LoggedException.Message);
                    }

                    //draw title
                    foreach (string line in exceptionTitleLines)
                    {
                        if (line == null)
                        {
                            continue;
                        }

                        if (titleLineStep < 120) //120 is a lenght of red field in the popup
                        {
                            font.DrawString(line, new Vector2(15, titleLineStep), 0.8f, Color.White);
                            

                            titleLineStep += 25;
                        }
                    }

                    exceptionTitleLines = null;
                    #endregion

                    #region error body (stack trace)
                    helpString = string.Empty;

                    //if body's lenght is more than lenght of error popup, then divide it into lines
                    if (smallFont.FontFace.MeasureString(_LoggedException.StackTrace).Length() > Cache.GraphicsDevice.Viewport.Width - 40)
                    {
                        //declare
                        int charProcessed = 1;
                        string stackTrace = _LoggedException.StackTrace;

                        //Loop and keep dividing until exception message still has some chars
                        while (stackTrace.Length > 0)
                        {
                            //keep dividing until each line is less than vieport's width
                            while (smallFont.FontFace.MeasureString(helpString).Length() < Cache.GraphicsDevice.Viewport.Width - 40)
                            {


                                //keep pulling chars out of error stack trace while it's less than vieport's width
                                helpString = stackTrace.Substring(0, charProcessed);
                                charProcessed += 1;

                                if (charProcessed > stackTrace.Length)
                                {
                                    break;
                                }
                            }

                            //add to the list of lines
                            if (helpString != string.Empty)
                            {
                                exceptionStackTraceLines.Add(helpString);

                            }

                            //remove  a help string from message
                            stackTrace = stackTrace.Remove(0, charProcessed - 1);
                            //reset char processed
                            charProcessed = 1;
                            helpString = string.Empty;
                        }

                    }
                    else
                    {
                        exceptionStackTraceLines.Add(_LoggedException.StackTrace);

                    }

                    //draw title
                    foreach (string line in exceptionStackTraceLines)
                    {

                        smallFont.DrawString(line, new Vector2(15, stackTraceStep), 0.8f, Color.Black);

                        stackTraceStep += 25;

                    }

                    exceptionStackTraceLines = null;
                    #endregion

                    //draw close button
                    #region close button
                    //close button:
                    Cache.Draw(closeButton, new Rectangle((Cache.GraphicsDevice.Viewport.Width / 2) - 100, Cache.GraphicsDevice.Viewport.Height - 70, 150, 60), Color.White);
                    //draw "Close" string on the button:
                    font.DrawString("Close", new Vector2((Cache.GraphicsDevice.Viewport.Width / 2) - 60, Cache.GraphicsDevice.Viewport.Height - 60), 0, Color.Black);

                    #endregion

                 
                    // Cache.ShowException = false;
                    //_LoggedException = null;


                }
            }
            catch (Exception ex)
            {
                Util.ErrorLogging.LogError(ex);
                return;
            }


        }

        /// <summary>
        /// stop drawing exception popup
        /// </summary>
        public static void CloseExceptionPopup()
        {
            _LoggedException = null;
            _ScreensSet = false;


        }




        #endregion


    }
}
